using System.Text;
using System;
using System.Data;
using System.Data.SqlClient;
using Csla;
using Csla.Data;
using Csla.Validation;
using BA.DAL;
using BA;

namespace BlazeApps.Library.Forum
{ 
	[Serializable()] 
	public class Topic : Csla.BusinessBase<Topic>
	{
        private BlazeApps.Library.ConfigSettings Config = new BlazeApps.Library.ConfigSettings();
        private BA.DAL.DBUtility DAL = new BA.DAL.DBUtility();
        private Procedures Procs = new Procedures();

		#region Business Properties and Methods

		//declare members
		private Guid _topicID = Guid.NewGuid();
		private Guid _forumID = Guid.Empty;
		private string _topicName = string.Empty;
		private Guid _userID = Guid.Empty;
        private SmartDate _created = new SmartDate(DateTime.Now);
		private int _views = 0;
		private int _postsCount = 0;
		private string _lastPostBy = string.Empty;
		private Guid _lastUserID = Guid.Empty;
        private SmartDate _lastPostDate = new SmartDate(DateTime.Now);
        private Boolean _Sticky = false;
        private Boolean _IsApproved = false;

		[System.ComponentModel.DataObjectField(true, false)]
		public Guid TopicID
		{
			get
			{
				CanReadProperty("TopicID", true);
				return _topicID;
			}
		}

		public Guid ForumID
		{
			get
			{
				CanReadProperty("ForumID", true);
				return _forumID;
			}
			set
			{
				CanWriteProperty("ForumID", true);
				if (!_forumID.Equals(value))
				{
					_forumID = value;
					PropertyHasChanged("ForumID");
				}
			}
		}

		public string TopicName
		{
			get
			{
				CanReadProperty("TopicName", true);
				return _topicName;
			}
			set
			{
				CanWriteProperty("TopicName", true);
				if (value == null) value = string.Empty;
				if (!_topicName.Equals(value))
				{
					_topicName = value;
					PropertyHasChanged("TopicName");
				}
			}
		}

		public Guid UserID
		{
			get
			{
				CanReadProperty("UserID", true);
				return _userID;
			}
			set
			{
				CanWriteProperty("UserID", true);
				if (!_userID.Equals(value))
				{
					_userID = value;
					PropertyHasChanged("UserID");
				}
			}
		}

		public DateTime Created
		{
			get
			{
				CanReadProperty("Created", true);
				return _created.Date;
			}
		}

		public string CreatedString
		{
			get
			{
				CanReadProperty("CreatedString", true);
				return _created.Text;
			}
			set
			{
				CanWriteProperty("CreatedString", true);
				if (value == null) value = string.Empty;
				if (!_created.Equals(value))
				{
					_created.Text = value;
					PropertyHasChanged("CreatedString");
				}
			}
		}

		public int Views
		{
			get
			{
				CanReadProperty("Views", true);
				return _views;
			}
			set
			{
				CanWriteProperty("Views", true);
				if (!_views.Equals(value))
				{
					_views = value;
					PropertyHasChanged("Views");
				}
			}
		}

		public int PostsCount
		{
			get
			{
				CanReadProperty("PostsCount", true);
				return _postsCount;
			}
			set
			{
				CanWriteProperty("PostsCount", true);
				if (!_postsCount.Equals(value))
				{
					_postsCount = value;
					PropertyHasChanged("PostsCount");
				}
			}
		}

		public string LastPostBy
		{
			get
			{
				CanReadProperty("LastPostBy", true);
				return _lastPostBy;
			}
			set
			{
				CanWriteProperty("LastPostBy", true);
				if (value == null) value = string.Empty;
				if (!_lastPostBy.Equals(value))
				{
					_lastPostBy = value;
					PropertyHasChanged("LastPostBy");
				}
			}
		}

		public Guid LastUserID
		{
			get
			{
				CanReadProperty("LastUserID", true);
				return _lastUserID;
			}
			set
			{
				CanWriteProperty("LastUserID", true);
				if (!_lastUserID.Equals(value))
				{
					_lastUserID = value;
					PropertyHasChanged("LastUserID");
				}
			}
		}

		public DateTime LastPostDate
		{
			get
			{
				CanReadProperty("LastPostDate", true);
				return _lastPostDate.Date;
			}
		}

		public string LastPostDateString
		{
			get
			{
				CanReadProperty("LastPostDateString", true);
				return _lastPostDate.Text;
			}
			set
			{
				CanWriteProperty("LastPostDateString", true);
				if (value == null) value = string.Empty;
				if (!_lastPostDate.Equals(value))
				{
					_lastPostDate.Text = value;
					PropertyHasChanged("LastPostDateString");
				}
			}
		}

        public Boolean Sticky
        {
            get
            {
                return _Sticky;
            }
            set
            {
                CanWriteProperty("Sticky", true);
                if (!_Sticky.Equals(value))
                {
                    _Sticky = value;
                    PropertyHasChanged("Sticky");
                }
            }
        }

        public Boolean IsApproved
        {
            get
            {
                return _IsApproved;
            }
            set
            {
                CanWriteProperty("IsApproved", true);
                if(!_IsApproved.Equals(value))
                {
                    _IsApproved = value;
                    PropertyHasChanged("IsApproved");
                }
            }
        }
 
		protected override object GetIdValue()
		{
			return _topicID;
		}

		#endregion //Business Properties and Methods

		#region Validation Rules
		private void AddCustomRules()
		{
			//add custom/non-generated rules here...
		}

		private void AddCommonRules()
		{
			//
			// TopicName
			//
			ValidationRules.AddRule(CommonRules.StringRequired, "TopicName");
		}

		protected override void AddBusinessRules()
		{
			AddCommonRules();
			AddCustomRules();
		}
		#endregion //Validation Rules

		#region Authorization Rules
		protected override void AddAuthorizationRules()
		{
			//TODO: Define authorization rules in Topic
			//AuthorizationRules.AllowRead("TopicID", "TopicReadGroup");
			//AuthorizationRules.AllowRead("ForumID", "TopicReadGroup");
			//AuthorizationRules.AllowRead("TopicName", "TopicReadGroup");
			//AuthorizationRules.AllowRead("UserID", "TopicReadGroup");
			//AuthorizationRules.AllowRead("Created", "TopicReadGroup");
			//AuthorizationRules.AllowRead("CreatedString", "TopicReadGroup");
			//AuthorizationRules.AllowRead("Views", "TopicReadGroup");
			//AuthorizationRules.AllowRead("PostsCount", "TopicReadGroup");
			//AuthorizationRules.AllowRead("LastPostBy", "TopicReadGroup");
			//AuthorizationRules.AllowRead("LastUserID", "TopicReadGroup");
			//AuthorizationRules.AllowRead("LastPostDate", "TopicReadGroup");
			//AuthorizationRules.AllowRead("LastPostDateString", "TopicReadGroup");

			//AuthorizationRules.AllowWrite("ForumID", "TopicWriteGroup");
			//AuthorizationRules.AllowWrite("TopicName", "TopicWriteGroup");
			//AuthorizationRules.AllowWrite("UserID", "TopicWriteGroup");
			//AuthorizationRules.AllowWrite("CreatedString", "TopicWriteGroup");
			//AuthorizationRules.AllowWrite("Views", "TopicWriteGroup");
			//AuthorizationRules.AllowWrite("PostsCount", "TopicWriteGroup");
			//AuthorizationRules.AllowWrite("LastPostBy", "TopicWriteGroup");
			//AuthorizationRules.AllowWrite("LastUserID", "TopicWriteGroup");
			//AuthorizationRules.AllowWrite("LastPostDateString", "TopicWriteGroup");
		}


		public static bool CanGetObject()
		{
			//TODO: Define CanGetObject permission in Topic
			return true;
			//if (Csla.ApplicationContext.User.IsInRole("TopicViewGroup"))
			//	return true;
			//return false;
		}

		public static bool CanAddObject()
		{
			//TODO: Define CanAddObject permission in Topic
			return true;
			//if (Csla.ApplicationContext.User.IsInRole("TopicAddGroup"))
			//	return true;
			//return false;
		}

		public static bool CanEditObject()
		{
			//TODO: Define CanEditObject permission in Topic
			return true;
			//if (Csla.ApplicationContext.User.IsInRole("TopicEditGroup"))
			//	return true;
			//return false;
		}

		public static bool CanDeleteObject()
		{
			//TODO: Define CanDeleteObject permission in Topic
			return true;
			//if (Csla.ApplicationContext.User.IsInRole("TopicDeleteGroup"))
			//	return true;
			//return false;
		}
		#endregion //Authorization Rules

		#region Factory Methods
		private Topic()
		{ /* require use of factory method */ }

		public static Topic NewTopic()
		{
			if (!CanAddObject())
				throw new System.Security.SecurityException("User not authorized to add a Topic");
			return DataPortal.Create<Topic>();
		}

		public static Topic GetTopic(Guid topicID)
		{
            //if (!CanGetObject())
            //    throw new System.Security.SecurityException("User not authorized to view a Topic");
			return DataPortal.Fetch<Topic>(new Criteria(topicID));
		}

		public static void DeleteTopic(Guid topicID)
		{
			if (!CanDeleteObject())
				throw new System.Security.SecurityException("User not authorized to remove a Topic");
			DataPortal.Delete(new Criteria(topicID));
		}

		public override Topic Save()
		{
			if (IsDeleted && !CanDeleteObject())
				throw new System.Security.SecurityException("User not authorized to remove a Topic");
			else if (IsNew && !CanAddObject())
				throw new System.Security.SecurityException("User not authorized to add a Topic");
			else if (!CanEditObject())
				throw new System.Security.SecurityException("User not authorized to update a Topic");

			return base.Save();
		}

		#endregion //Factory Methods

		#region Data Access

		#region Criteria

		[Serializable()]
		private class Criteria
		{
			public Guid TopicID;

			public Criteria(Guid topicID)
			{
				this.TopicID = topicID;
			}
		}

		#endregion //Criteria

		#region Data Access - Create
		[RunLocal]
		protected override void DataPortal_Create()
		{
			ValidationRules.CheckRules();
		}

		#endregion //Data Access - Create

		#region Data Access - Fetch
		private void DataPortal_Fetch(Criteria criteria)
		{
            ExecuteFetch(criteria);
		}

		private void ExecuteFetch(Criteria criteria)
		{
            DAL.CreateDBObjects(Config.ConnectionString, Config.Provider);

            DAL.AddParameter("@TopicID", criteria.TopicID);

            using(SafeDataReader dr = new SafeDataReader(DAL.ExecuteReader(Procs.GetTopicByTopicID.ToString().Trim(), CommandType.Text, ConnectionState.Open)))
            {
                FetchObject(dr);
                ValidationRules.CheckRules();

                //load child object(s)
                FetchChildren(dr);
            }
		}

		private void FetchObject(SafeDataReader dr)
		{
			dr.Read();
			_topicID = dr.GetGuid("TopicID");
			_forumID = dr.GetGuid("ForumID");
			_topicName = dr.GetString("TopicName");
			_userID = dr.GetGuid("UserID");
			_created = dr.GetSmartDate("Created", _created.EmptyIsMin);
			_views = dr.GetInt32("Views");
			_postsCount = dr.GetInt32("PostsCount");
			_lastPostBy = dr.GetString("LastPostBy");
			_lastUserID = dr.GetGuid("LastUserID");
			_lastPostDate = dr.GetSmartDate("LastPostDate", _lastPostDate.EmptyIsMin);
            _Sticky = dr.GetBoolean("sticky");
            _IsApproved = dr.GetBoolean("IsApproved");
		}

		private void FetchChildren(SafeDataReader dr)
		{
		}
		#endregion //Data Access - Fetch

		#region Data Access - Insert
        protected override void DataPortal_Insert()
        {
            ExecuteInsert();
        }

        private void ExecuteInsert()
        {
            DAL.CreateDBObjects(Config.ConnectionString, Config.Provider);

            AddInsertParameters(ref DAL);

            DAL.ExecuteNonQuery(Procs.InsertTopic.ToString().Trim(), CommandType.Text, ConnectionState.Open);
        }

        private void AddInsertParameters(ref BA.DAL.DBUtility DAL)
		{
			DAL.AddParameter("@TopicID", _topicID);
			DAL.AddParameter("@ForumID", _forumID);
			DAL.AddParameter("@TopicName", _topicName);
			DAL.AddParameter("@UserID", _userID);
			DAL.AddParameter("@Created", _created.DBValue);
			DAL.AddParameter("@Views", _views);
			DAL.AddParameter("@PostsCount", _postsCount);
			DAL.AddParameter("@LastPostBy", _lastPostBy);
			DAL.AddParameter("@LastUserID", _lastUserID);
			DAL.AddParameter("@LastPostDate", _lastPostDate.DBValue);
            DAL.AddParameter("@sticky", _Sticky);
            DAL.AddParameter("@IsApproved", _IsApproved);
		}
		#endregion //Data Access - Insert

		#region Data Access - Update
        protected override void DataPortal_Update()
        {
            if (base.IsDirty)
            {
                ExecuteUpdate();
            }
        }

        private void ExecuteUpdate()
        {
            DAL.CreateDBObjects(Config.ConnectionString, Config.Provider);

            AddUpdateParameters(ref DAL);

            DAL.ExecuteNonQuery(Procs.UpdateTopic.ToString().Trim(), CommandType.Text, ConnectionState.Open);
        }

        private void AddUpdateParameters(ref BA.DAL.DBUtility DAL)
		{
			DAL.AddParameter("@TopicID", _topicID);
			DAL.AddParameter("@ForumID", _forumID);
			DAL.AddParameter("@TopicName", _topicName);
			DAL.AddParameter("@UserID", _userID);
			DAL.AddParameter("@Created", _created.DBValue);
			DAL.AddParameter("@Views", _views);
			DAL.AddParameter("@PostsCount", _postsCount);
			DAL.AddParameter("@LastPostBy", _lastPostBy);
			DAL.AddParameter("@LastUserID", _lastUserID);
			DAL.AddParameter("@LastPostDate", _lastPostDate.DBValue);
            DAL.AddParameter("@sticky", _Sticky);
            DAL.AddParameter("@IsApproved", _IsApproved);
		}

		private void UpdateChildren(SqlConnection cn)
		{
		}
		#endregion //Data Access - Update

		#region Data Access - Delete
        protected override void DataPortal_DeleteSelf()
        {
            DataPortal_Delete(new Criteria(_topicID));
        }

        private void DataPortal_Delete(Criteria criteria)
        {
            ExecuteDelete(criteria);
        }

        private void ExecuteDelete(Criteria criteria)
        {
            DAL.CreateDBObjects(Config.ConnectionString, Config.Provider);

            AddDeleteParameters(ref DAL, criteria);

            DAL.ExecuteNonQuery(Procs.DeleteTopic.ToString().Trim(), CommandType.Text, ConnectionState.Open);

            ExecuteDeleteTopicPosts(criteria);
        }

        private void ExecuteDeleteTopicPosts(Criteria criteria)
        {
            DAL.CreateDBObjects(Config.ConnectionString, Config.Provider);

            AddDeleteParameters(ref DAL, criteria);

            DAL.ExecuteNonQuery(Procs.DeleteTopicPosts.ToString().Trim(), CommandType.Text, ConnectionState.Open);
        }

        private void AddDeleteParameters(ref BA.DAL.DBUtility DAL, Criteria criteria)
        {
            DAL.AddParameter("@TopicID", criteria.TopicID);
        }
		#endregion //Data Access - Delete
		#endregion //Data Access
	}
}
